<!--

 * @Description: 表单项属性，控件属性面板
-->
<template>
  <div class="properties-content">
    <div class="properties-body" v-if="formConfig.currentItem?.itemProps">
      <Empty class="hint-box" v-if="!formConfig.currentItem.component" description="未选择控件" />
      <Form
        v-else
        label-align="left"
        layout="horizontal"
        :colon="false"
        ref="formItemPropsRef"
        :model="formConfig.currentItem"
        :labelCol="{ style: { width: '92px', color: '#333', fontWeight: '600' } }"
      >
        <div v-for="item of baseFormItemProps" :key="item.name">
          <FormItem
            :label="item.label"
            :name="item.name"
            :required="item.required"
            v-if="showProps(item.exclude)"
          >
            <component
              class="component-props"
              v-bind="
                isFunction(item.componentProps)
                  ? item.componentProps({
                      record: formConfig.currentItem,
                      client,
                    })
                  : item.componentProps
              "
              :is="item.component"
              v-model:value="formConfig.currentItem[item.name]"
            />
          </FormItem>
        </div>
        <div v-for="item of advanceFormItemProps" :key="item.name">
          <FormItem :label="item.label" v-if="showProps(item.exclude)">
            <component
              class="component-props"
              v-bind="item.componentProps"
              :is="item.component"
              v-model:value="formConfig.currentItem.itemProps[item.name]"
            />
          </FormItem>
        </div>
        <div v-for="item of advanceFormItemColProps" :key="item.name">
          <FormItem :label="item.label" v-if="showProps(item.exclude)">
            <component
              class="component-props"
              v-bind="item.componentProps"
              :is="item.component"
              v-model:value="formConfig.currentItem.itemProps[item.name]['span']"
            />
          </FormItem>
        </div>
        <div v-for="item of formItemColProps" :key="item.name">
          <FormItem :label="item.label" v-if="showProps(item.exclude)">
            <component
              class="component-props"
              v-bind="item.componentProps"
              :is="item.component"
              v-model:value="formConfig.currentItem[item.name]['span']"
            />
          </FormItem>
        </div>
        <FormItem label="说明/帮助" v-if="showProps(viewExcloud)">
          <div class="input">
            <Textarea v-model:value="formConfig.currentItem.helpMessage" :rows="1" />
          </div>
          <Checkbox v-model:checked="formConfig.currentItem.helpBefore">标题前 </Checkbox>
          <Checkbox v-model:checked="formConfig.currentItem.helpAfter">标题后 </Checkbox>
        </FormItem>

        <FormItem v-if="showProps(viewExcloud)" label="校验规则">
          <a-button @click="handleItemRules()">编辑规则</a-button>
          <FormItemRuleConfig @register="registerItemRulesModal" />
        </FormItem>

        <FormItem label="控制属性" v-if="controlPropsList.length">
          <template v-for="item of controlPropsList" :key="item.name">
            <Checkbox v-model:checked="formConfig.currentItem.itemProps[item.name]">
              {{ item.label }}
            </Checkbox>
          </template>
        </FormItem>

        <template v-if="['Upload', 'Signature'].includes(formConfig.currentItem.component)">
          <FormItem
            label="资源类型"
            :rules="[
              {
                required: true,
                message: '请选择资源类型',
                trigger: 'change',
              },
            ]"
            name="resourceType"
          >
            <RadioGroup
              v-model:value="formConfig.currentItem!.resourceType"
              :options="FileSourceTypeOptions"
            />
          </FormItem>

          <FormItem
            label="资源配置"
            name="attachment"
            :rules="[{ required: true, validator: validatorUpload }]"
          >
            <ApiSelect
              v-model:value="formConfig.currentItem!.resourceCode"
              :api="getOptionsResource"
              showSearch
              :fieldNames="{
                label: 'name',
                value: 'code',
              }"
              :allowClear="formConfig.currentItem!.resourceType !== 1"
              placeholder="请选择资源"
              :filterOption="false"
              :params="searchSourceParams"
              @search="onSearch"
            />
            <div class="mt-4" v-if="formConfig.currentItem!.resourceType !== 1">
              <a-button @click="handleUploadConfig()"> 自定义配置 </a-button>
            </div>
          </FormItem>
          <UploadConfigModal @register="registerConfigModal" />
        </template>
        <template v-if="dataSourceComps.includes(formConfig.currentItem.component)">
          <FormItem required name="dataSourceType" label="数据来源">
            <Select
              :fieldNames="{
                label: 'connName',
                value: 'connCode',
              }"
              v-model:value="formConfig.currentItem!.dataSourceType"
              :options="dataSourceTypeOptions"
              placeholder="请选择数据来源"
              showSearch
            />
          </FormItem>

          <FormItem label="固定数据" v-if="formConfig.currentItem!.dataSourceType === '-1'">
            <FormOptions />
          </FormItem>
          <FormItem
            label="字典类型"
            :rules="[{ required: true, message: '请选择字典类型', validator: validDictType }]"
            name="dictType"
            v-else-if="formConfig.currentItem!.dataSourceType === '-2'"
          >
            <ApiSelect
              v-model:value="formConfig.currentItem!.dictType"
              :api="getDictListApi"
              showSearch
              placeholder="请选择字典类型"
              :filterOption="false"
              :params="searchParams"
              @search="onSearch"
            />
          </FormItem>
          <FormItem
            label="资源配置"
            name="resourceCode"
            v-else-if="formConfig.currentItem!.dataSourceType === '-3'"
            required
          >
            <ApiSelect
              v-model:value="formConfig.currentItem!.resourceCode"
              :api="getOptionsResource"
              showSearch
              :fieldNames="{
                label: 'name',
                value: 'code',
              }"
              placeholder="请选择资源"
              :filterOption="false"
              :params="searchSourceParams"
              @search="onSearch"
            />
          </FormItem>
          <template
            v-else-if="
              ['ApiSelect', 'ApiTreeSelect', 'CheckboxGroup', 'RadioGroup'].includes(
                formConfig.currentItem.component,
              )
            "
          >
            <FormItem
              label="SQL定义"
              name="dataForm"
              :rules="[
                {
                  required: true,
                  message: '请选择资源类型',
                  validator: validatorSQL,
                },
              ]"
            >
              <a-button @click="handleSQLConfig()"> 编辑SQL </a-button>
              <SQLConfigModal @register="registerConfigSQLModal" />
            </FormItem>
          </template>

          <template v-if="['SubTable'].includes(formConfig.currentItem.component)">
            <FormItem
              label="数据源配置"
              required
              name="simpleChildTable"
              :rules="[
                {
                  required: true,
                  validator: validatorSubTable,
                },
              ]"
            >
              <a-button @click="handleSubTableConfig()"> 编辑数据源 </a-button>
              <SubTableConfigModal @register="registerConfigSubTableModal" />
            </FormItem>
          </template>
        </template>
        <FormItem v-if="showProps(viewExcloud)" label="函数定义">
          <a-button @click="handleEvent()">编辑函数</a-button>
          <FormEventConfig @register="registerEventModal" />
        </FormItem>

        <FormItem
          label="必选提示"
          v-if="
            !['Grid'].includes(formConfig.currentItem.component) &&
            formConfig.currentItem.itemProps['required']
          "
        >
          <!-- <Switch v-model:checked="formConfig.currentItem.itemProps['required']" /> -->
          <Input
            v-if="formConfig.currentItem.itemProps['required']"
            v-model:value="formConfig.currentItem.itemProps['message']"
            placeholder="请输入必选提示"
          />
        </FormItem>
      </Form>
    </div>
  </div>
</template>
<script lang="ts">
  import { computed, defineComponent, watch, ref, unref } from 'vue';
  import { isFunction } from '/@/utils/is';
  import { useFormDesignStoreWithOut } from '/@/store/modules/formDesign';
  import { useModal } from '/@/components/Modal';
  import { getDBListApi } from '/@/api/database/account';
  import { getDictPageListApi } from '/@/api/admin/dict';
  import { getOptionsResource } from '/@/api/admin/resoure';
  import { FileSourceTypeOptions } from '/@/views/config-center/model-design/components/consts';

  import {
    baseFormItemControlAttrs,
    baseFormItemProps,
    advanceFormItemProps,
    advanceFormItemColProps,
    formItemColProps,
  } from '../../VFormDesign/config/formItemPropsConfig';
  import FormOptions from './FormOptions.vue';

  import {
    Input,
    Form,
    FormItem,
    Switch,
    Checkbox,
    Select,
    Slider,
    Col,
    RadioGroup,
    CheckboxGroup,
    Textarea,
  } from 'ant-design-vue';
  import HEmpty from '/@/components/HEmpty/index.vue';
  import FormEventConfig from './FormEventConfig.vue';
  import FormItemRuleConfig from './FormItemRuleConfig.vue';
  import UploadConfigModal from './UploadConfigModal.vue';
  import SQLConfigModal from './SQLConfigModal.vue';
  import SubTableConfigModal from './SubTableConfigModal.vue';

  import { ApiSelect } from '/@/components/Form/index';

  import { useFormDesignState } from '../../../hooks/useFormDesignState';
  import { isArray } from '/@/utils/is';
  // import { verify } from '/@/utils/validator';
  import { useDebounceFn } from '@vueuse/core';

  const dataSourceComps = [
    'ApiSelect',
    'CheckboxGroup',
    'RadioGroup',
    'ApiTreeSelect',
    'Upload',
    'SubTable',
    'Signature',
  ];

  export default defineComponent({
    name: 'FormItemProps',
    components: {
      Empty: HEmpty,
      Input,
      Textarea,
      Form,
      FormItem,
      Switch,
      Checkbox,
      CheckboxGroup,
      Select,
      Slider,
      Col,
      RadioGroup,
      ApiSelect,
      FormOptions,
      FormEventConfig,
      UploadConfigModal,
      SQLConfigModal,
      SubTableConfigModal,
      FormItemRuleConfig,
    },
    // props: {} as PropsOptions,

    setup() {
      const formDesignStore = useFormDesignStoreWithOut();
      const { formConfig, client } = useFormDesignState();
      const formItemPropsRef = ref();
      watch(formItemPropsRef, () => {
        formDesignStore.setFormItemPropsRef(formItemPropsRef);
      });

      const searchSourceParams = computed<Recordable>(() => {
        return {
          code: unref(keyword),
          classify: ['Upload', 'Signature'].includes(formConfig.value.currentItem!.component)
            ? 1
            : 0,
        };
      });

      watch(
        () => formConfig.value.currentItem,
        () => {
          if (formConfig.value.currentItem) {
            const { itemProps, colProps, updateType } = formConfig.value.currentItem;

            formConfig.value.currentItem.updateType = updateType ?? 1;
            const { labelCol, wrapperCol } = itemProps || {};
            formConfig.value.currentItem.itemProps = itemProps || {};

            const labelSpan = formConfig.value.labelCol!.span;

            formConfig.value.currentItem.itemProps.labelCol = labelCol || { span: labelSpan };

            const wrapperSpan = formConfig.value.wrapperCol!.span;

            formConfig.value.currentItem.itemProps.wrapperCol = wrapperCol || { span: wrapperSpan };

            const baseSpan = formConfig.value.baseColProps.span;
            formConfig.value.currentItem.colProps = colProps || { span: baseSpan };

            const inset = !['Upload', 'SubTable', 'Signature', 'ApiTreeSelect'].includes(
              formConfig.value.currentItem!.component,
            );

            getDataSourceOptions(inset);
          }
        },
        { deep: true, immediate: true },
      );
      const showProps = (exclude: string[] | undefined) => {
        if (!exclude) {
          return true;
        }
        return isArray(exclude) ? !exclude.includes(formConfig.value.currentItem!.component) : true;
      };

      const controlPropsList = computed(() => {
        // console.log('const list2 = computed(() => {');
        return baseFormItemControlAttrs.filter((item) => {
          return showProps(item.exclude);
        });
      });

      const [registerEventModal, { openModal: eventModal }] = useModal();
      const [registerConfigModal, { openModal: configModal }] = useModal();
      const [registerConfigSQLModal, { openModal: configSQLModal }] = useModal();
      const [registerConfigSubTableModal, { openModal: configSubTableModal }] = useModal();
      const [registerItemRulesModal, { openModal: itemRulesModal }] = useModal();

      const handleEvent = () => {
        eventModal(true, {
          isForm: false,
        });
      };

      const handleUploadConfig = () => {
        configModal(true, {});
      };
      const dataSourceTypeOptions = ref<any[]>([]);

      async function getDataSourceOptions(inset) {
        const data = await getDBListApi();

        data.forEach((e) => {
          e.connName = `${e.connName} (${e.connCode})`;
        });
        if (inset) {
          data.unshift(
            // @ts-ignore
            ...[
              { connName: '资源管理', connCode: '-3' },
              { connName: '数据字典', connCode: '-2' },
              { connName: '固定数据', connCode: '-1' },
            ],
          );
        }

        dataSourceTypeOptions.value = data;
      }
      const keyword = ref<string>('');
      const searchParams = computed<Recordable>(() => {
        return { dictType: unref(keyword) };
      });

      function onSearch(value: string) {
        keyword.value = value;
      }
      async function getDictListApi(data) {
        const ret = await getDictPageListApi(data);
        ret.records.forEach((el) => {
          el.label = `${el.description}(${el.dictType})`;
          el.value = el.dictType;
        });
        return ret.records;
      }

      const validatorUpload = (): Promise<void> => {
        return new Promise(async (resolve, reject) => {
          if (formConfig.value.currentItem?.resourceType === 1) {
            if (!formConfig.value.currentItem?.resourceCode) {
              reject('请选择文件上传资源');
            }
            return resolve();
          }
          const value = formConfig.value.currentItem?.attachment;
          if (!value) return reject('请配置文件上传资源');
          return resolve();
        });
      };
      const validatorSQL = (): Promise<void> => {
        return new Promise(async (resolve, reject) => {
          const value = formConfig.value.currentItem?.dataForm;
          if (!value) return reject('请配置SQL定义');
          return resolve();
        });
      };
      const validatorSubTable = (): Promise<void> => {
        return new Promise(async (resolve, reject) => {
          const value = formConfig.value.currentItem?.simpleChildTable;
          if (!value) return reject('请配置子表数据源');
          return resolve();
        });
      };
      const handleSQLConfig = () => {
        configSQLModal(true, {});
      };
      const handleSubTableConfig = () => {
        configSubTableModal(true, {});
      };
      const handleItemRules = () => {
        itemRulesModal(true, {});
      };

      return {
        viewExcloud: ['Grid', 'HFormTitle'],
        client,
        formItemPropsRef,
        baseFormItemProps,
        advanceFormItemProps,
        advanceFormItemColProps,
        formItemColProps,
        formConfig,
        controlPropsList,
        searchParams,
        searchSourceParams,
        dataSourceComps,
        dataSourceTypeOptions,
        FileSourceTypeOptions,
        registerConfigModal,
        registerEventModal,
        registerItemRulesModal,
        showProps,
        isFunction,
        handleEvent,
        handleUploadConfig,
        getDBListApi,
        onSearch: useDebounceFn(onSearch, 300),
        validatorUpload,
        getDictListApi,
        getOptionsResource,
        validatorSQL,
        handleSQLConfig,
        registerConfigSQLModal,
        registerConfigSubTableModal,
        handleSubTableConfig,
        validatorSubTable,
        handleItemRules,
        validDictType: (): Promise<void> =>
          new Promise((resolve, reject) => {
            if (formConfig.value.currentItem!.dictType) {
              resolve();
            } else {
              reject();
            }
          }),
      };
    },
  });
</script>
